<html>
<head>
<title>CpcPaChi - Version 0.13</title>
<style type="text/css">
span {
    font-family: 'Courier New';
    font-size: 10pt;
    color: #000000;
}
.sc0 {
    color: #808080;
}
.sc3 {
    color: #008080;
}
.sc4 {
    color: #FF8000;
}
.sc5 {
    font-weight: bold;
    color: #0000FF;
}
.sc7 {
    color: #808080;
}
.sc9 {
    color: #804000;
}
.sc10 {
    font-weight: bold;
    color: #000080;
}
.sc11 {
}
</style>
</head>
<body>
<h2>Un compilador sencillo paso a paso (13 - Estructuras repetitivas)</h2>

<p align="right">(Volver al <a href="doc.html">&iacute;ndice</a>) </p>

<p>Si sabemos c&oacute;mo hacer saltos, y c&oacute;mo comprobaciones del
tipo &quot;if..then..else&quot;, crear construcciones como &quot;while&quot;
y como &quot;repeat..until&quot; deber&iacute;a ser muy f&aacute;cil. Tampoco
deber&iacute;a ser muy complejo crear secuencias &quot;for&quot;.
Vamos con ello...</p>

<p>Comencemos por "while". Un bloque como</p>

<pre><code>while condicion do
  begin
  bloque1
  end
restoDePrograma</code></pre>

<p>Se podr&iacute;a reescribir como</p>

<pre><code>
inicioWhile:
if not condicion then goto inicioRestoDePrograma;
  bloque1
  goto inicioWhile;
inicioRestoDePrograma:
  restoDePrograma</code></pre>

<p>Que, al igual que ocurr&iacute;a con &quot;if&quot;, ya tiene una traducci&oacute;n
casi directa a ensamblador (y, por tanto, a c&oacute;digo
m&aacute;quina).</p>


<p><br />El caso de &quot;repeat..until&quot; es
a&uacute;n m&aacute;s sencillo. El c&oacute;digo
fuente ser&iacute;a</p>

<pre><code>repeat
  bloque1
until condicion;
restoDePrograma</code></pre>

<p>Se podr&iacute;a reescribir en forma muy cercana al
ensamblador como</p>

<pre><code>
inicioRepeat:
  bloque1
if not condicion then goto inicioRepeat;
restoDePrograma</code></pre>


<p><br />Mientras que el bucle "for" es apenas ligeramente
m&aacute;s complicado:</p>

<pre><code>for variable := valorInicial to valorFinal do
  begin
  bloque1
  end
restoDePrograma</code></pre>

<p>Quedar&iacute;a como</p>

<pre><code>variable := valorInicial;
inicioFor:
if variable > valorFinal then goto inicioRestoDePrograma;
  bloque1
  inc(variable)
  goto inicioFor;
inicioRestoDePrograma:
  restoDePrograma</code></pre>

<p>(ignoramos por ahora el caso de usar "downto" en vez de "to").</p>

<p>La sintaxis &quot;real&quot; en nuestro fuente es algo m&aacute;s compleja, pero sigue claramente la estructura expresada anteriormente. Por ejemplo, el &aacute;nalisis de &quot;While&quot; se convertir&iacute;a en:</p>

<pre><code>void analizarWHILE()
{
string ident1, ident2, ordenDo;
string tipoComparacion;
string ifActual;

/* Uso el numero de IF actual para generar
   las etiquetas de salto. Lo copio en una variable
   local para evitar modificaciones inesperadas
   en IF anidados */
ifActual = Convert.ToString(numeroIFactual);
numeroIFactual ++;
miTablaSimb.Insertar(&quot;WHILE_&quot;+ifActual, tipoId.LABEL,
  tamDato.INTEGER, 0 );
miGenerador.genLABEL(&quot;WHILE_&quot;+ifActual);
miTablaSimb.Insertar(&quot;FIN_WHILE_&quot;+ifActual, tipoId.LABEL,
  tamDato.INTEGER, 0 );
// Comienza el analisis en si
ident1 = miLexer.ObtenerIdentificador().ToUpper();
tipoComparacion = &quot;&quot;+miLexer.LeerCualquierSimbolo(); // ### A mejorar
ident2 = miLexer.ObtenerEnteroOIdentificador().ToUpper();
miGenerador.genComentario(&quot;WHILE &quot;+ident1+tipoComparacion+ident2);
ordenDo = miLexer.ObtenerIdentificador().ToUpper();
if (ordenDo != &quot;DO&quot;) miLexer.ErrorFatal(&quot;WHILE sin DO&quot;);
miGenerador.genIF(ident1,
  inversoComparacion(tipoComparacion), ident2);
miGenerador.genDireccSinGOTO(&quot;FIN_WHILE_&quot;+ifActual);
// Bloque de codigo tras WHILE
analizarBloqueBEGIN_END();
miGenerador.genGOTO(&quot;WHILE_&quot;+ifActual);
miGenerador.genLABEL(&quot;FIN_WHILE_&quot;+ifActual);
miLexer.LeerSimbolo(';');
}
</code></pre>

<p>Ahora es capaz de compilar programas como &eacute;ste:</p>

<pre><code>program ej13; { Ejemplo 13 de CpcPaChi }
var
  color: byte;  
  
begin
  cpcMode(1);
  (* Prueba de for *)
  locate(10,5);
  paper(0);
  for color := 1 to 3 do
    begin
    pen(color);
    writeChar('*');
    end;

    (* Prueba de while *)
  locate(10,7);
  paper(1);
  color := 2;
  while color &lt; 3 do
    begin
    pen(color);
    writeChar('+');
    inc(color);
    end;

    (* Prueba de repeat *) 
    
  locate(10,9); 
  paper(3);
  color := 2;
  repeat
    pen(color);
    writeChar('@');
    dec(color);
  until color = 0;
    
  paper(0);
  pen(1);
end.
</code></pre>

<p>Que dar&iacute;a este resultado en pantalla:</p>

<img src="ej013.png" alt="Ejemplo 13">

<p>Aun as&iacute;, hay cosas que mejorar (en una versi&oacute;n posterior).
Unas son fallos claros de la versi&oacute;n actual y otras son mejoras necesarias.
La primera y m&aacute;s evidente es que nuestro analizador l&eacute;xico
no reconoce operadores de formados por dos letras: ni
&quot;&lt;=&quot;, ni &quot;&gt;=&quot;, ni &quot;&lt;&gt;&quot;.
Tampoco se crea correctamente el c&oacute;digo objetivo para estas comparaciones.
Por supuesto,
tampoco permite AND, OR y NOT para formar condiciones
m&aacute;s complejas. Tampoco sabemos analizar expresiones
matem&aacute;ticas m&aacute;s elaboradas, de modo que no podemos hacer
cosas como &quot;if a &gt; x+1 then ...&quot;</p>

<p><br>
  Como siempre, para m&aacute;s detalles, todo el c&oacute;digo est&aacute; en la p&aacute;gina del proyecto en Google Code:<br />
  <br />
  <a href="http://code.google.com/p/cpcpachi/">http://code.google.com/p/cpcpachi/</a></p>
<p align="right">(Volver al <a href="doc.html">&iacute;ndice</a>) </p>
</body>
</html>
